/*
 * @Authoryour name
 * @Date2020-11-30 22:24:55
 * @LastEditTime2020-11-30 22:24:55
 * @LastEditorsyour name
 * @DescriptionIn User Settings Edit
 * @FilePath\STM32H750_FreeRTOS\Bsp\bsp_uart\bsp_uart.c
 */ 

#include "bsp_uart.h"
#include <stdio.h>

#define UART_ENABLE_DMA     FALSE
#define UART_USE_HAL        TRUE

static void bsp_uart_gpio_init(void);
static void bsp_uart_module_init(void);
static void bsp_uart_dma_init(void);

static void bsp_uart_gpio_deinit(void);
static void bsp_uart_module_deinit(void);
static void bsp_uart_dma_deinit(void);

static UART_HandleTypeDef _uart_handle;

uint8_t debug_uart_rx_buffer[DEBUG_UART_RX_BUFFER_SIZE] = {0};
uart_rx_t debug_uart_rx = 
{
    .old_pos   = 0,
    .rx_buffer = (uint8_t *)debug_uart_rx_buffer,
};

/**
 * @brief  
 * @param  
 * @retval 
 */
void bsp_uart_init(void)
{
    bsp_uart_gpio_init();
    bsp_uart_module_init();
#if UART_ENABLE_DMA
    bsp_uart_dma_init();
#endif

#if UART_ENABLE_DMA
    LL_USART_EnableDMAReq_RX(DEBUG_UART);
#endif
    LL_USART_Enable(DEBUG_UART);
#if UART_ENABLE_DMA
    LL_DMA_EnableStream(DEBUG_UART_RX_DMA, DEBUG_UART_RX_DMA_STREAM);
#endif
}

/**
 * @brief  
 * @param  
 * @retval 
 */
void bsp_uart_deinit(void)
{
#if UART_ENABLE_DMA
    LL_DMA_DisableStream(DEBUG_UART_RX_DMA, DEBUG_UART_RX_DMA_STREAM);
#endif
    LL_USART_Disable(DEBUG_UART);
#if UART_ENABLE_DMA
    LL_USART_DisableDMAReq_RX(DEBUG_UART);
#endif

#if UART_ENABLE_DMA
    bsp_uart_dma_deinit();
#endif
    bsp_uart_module_deinit();
    bsp_uart_gpio_deinit();
}

/**
 * @brief  
 * @param  
 * @retval 
 */
static void bsp_uart_gpio_init(void)
{
    LL_GPIO_InitTypeDef GpioInit;

    DEBUG_UART_IO_CLK_EN();

    GpioInit.Mode       = LL_GPIO_MODE_ALTERNATE;
    GpioInit.Pin        = DEBUG_UART_TX_PIN;
    GpioInit.Alternate  = GPIO_AF8_UART4;
    GpioInit.Speed      = GPIO_SPEED_HIGH;
    GpioInit.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    GpioInit.Pull       = LL_GPIO_PULL_NO;
    LL_GPIO_Init(DEBUG_UART_TX_PORT, &GpioInit);

    GpioInit.Mode       = LL_GPIO_MODE_ALTERNATE;
    GpioInit.Pin        = DEBUG_UART_RX_PIN;
    GpioInit.Alternate  = GPIO_AF8_UART4;
    GpioInit.Speed      = GPIO_SPEED_HIGH;
    GpioInit.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
    GpioInit.Pull       = LL_GPIO_PULL_NO;
    LL_GPIO_Init(DEBUG_UART_RX_PORT, &GpioInit);
}

/**
 * @brief  
 * @param  
 * @retval 
 */
static void bsp_uart_module_init(void)
{
    
    DEBUG_UART_CLK_EN();
#if (!UART_USE_HAL)
    LL_USART_InitTypeDef UartInit;
    UartInit.BaudRate            = DEBUG_UART_BAUDRATE;
    UartInit.DataWidth           = LL_USART_DATAWIDTH_8B;
    UartInit.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
    UartInit.OverSampling        = LL_USART_OVERSAMPLING_16;
    UartInit.Parity              = LL_USART_PARITY_NONE;
    UartInit.PrescalerValue      = LL_USART_PRESCALER_DIV1;
    UartInit.StopBits            = LL_USART_STOPBITS_1;
    UartInit.TransferDirection   = LL_USART_DIRECTION_TX_RX;
    LL_USART_Init(DEBUG_UART, &UartInit);
    LL_USART_SetTXFIFOThreshold(DEBUG_UART, LL_USART_FIFOTHRESHOLD_7_8);
    LL_USART_SetRXFIFOThreshold(DEBUG_UART, LL_USART_FIFOTHRESHOLD_7_8);
    LL_USART_EnableFIFO(DEBUG_UART);
    LL_USART_ConfigAsyncMode(DEBUG_UART);
    // LL_USART_EnableIT_RXNE_RXFNE(DEBUG_UART);
#else
    _uart_handle.Instance            = DEBUG_UART;
    _uart_handle.Init.BaudRate       = DEBUG_UART_BAUDRATE;
    _uart_handle.Init.WordLength     = UART_WORDLENGTH_8B;
    _uart_handle.Init.HwFlowCtl      = UART_HWCONTROL_NONE;
    _uart_handle.Init.OverSampling   = UART_OVERSAMPLING_16;
    _uart_handle.Init.Parity         = UART_PARITY_NONE;
    _uart_handle.Init.ClockPrescaler = UART_PRESCALER_DIV1;
    _uart_handle.Init.StopBits       = UART_STOPBITS_1;
    _uart_handle.Init.Mode           = UART_MODE_TX_RX;
    HAL_UART_Init(&_uart_handle);
    HAL_UARTEx_SetTxFifoThreshold(&_uart_handle, UART_TXFIFO_THRESHOLD_7_8);
    HAL_UARTEx_SetRxFifoThreshold(&_uart_handle, UART_RXFIFO_THRESHOLD_7_8);
    HAL_UARTEx_EnableFifoMode(&_uart_handle);
#endif
    
    // NVIC_SetPriority(UART4_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    // NVIC_EnableIRQ(UART4_IRQn);
}

/**
 * @brief  
 * @param  
 * @retval 
 */
static void bsp_uart_dma_init(void)
{
    LL_DMA_InitTypeDef DmaInit;

    DEBUG_UART_DMA_CLK_EN();

    DmaInit.Direction              = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
    DmaInit.MemoryOrM2MDstAddress  = (uint32_t)debug_uart_rx_buffer;
    DmaInit.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
    DmaInit.MemoryOrM2MDstIncMode  = LL_DMA_MEMORY_INCREMENT;
    DmaInit.PeriphOrM2MSrcAddress  = (uint32_t)(&DEBUG_UART->RDR);
    DmaInit.PeriphOrM2MSrcDataSize = LL_DMA_MDATAALIGN_BYTE;
    DmaInit.PeriphOrM2MSrcIncMode  = LL_DMA_PERIPH_NOINCREMENT;
    DmaInit.Mode                   = LL_DMA_MODE_CIRCULAR;
    DmaInit.Priority               = LL_DMA_PRIORITY_HIGH;
    DmaInit.FIFOMode               = LL_DMA_FIFOMODE_DISABLE;
    DmaInit.PeriphRequest          = LL_DMAMUX1_REQ_UART4_RX;
    DmaInit.NbData                 = DEBUG_UART_RX_BUFFER_SIZE;
    LL_DMA_Init(DEBUG_UART_RX_DMA, DEBUG_UART_RX_DMA_STREAM, &DmaInit);
}

/**
 * @brief  
 * @param  
 * @retval 
 */
static void bsp_uart_gpio_deinit(void)
{
    LL_GPIO_DeInit(DEBUG_UART_TX_PORT);
    LL_GPIO_DeInit(DEBUG_UART_RX_PORT);
}

/**
 * @brief  
 * @param  
 * @retval 
 */
static void bsp_uart_module_deinit(void)
{
#if (!UART_USE_HAL)
    LL_USART_DeInit(DEBUG_UART);
#else
    HAL_UART_DeInit(&_uart_handle);
#endif
}

/**
 * @brief  
 * @param  
 * @retval 
 */
static void bsp_uart_dma_deinit(void)
{
    LL_DMA_DeInit(DEBUG_UART_RX_DMA, DEBUG_UART_RX_DMA_STREAM);
}

/**
 * @brief  
 * @param  
 * @retval 
 */
void UART4_IRQHandler(void)
{
    // if(LL_USART_IsActiveFlag_RXNE_RXFNE(DEBUG_UART))
    // {
    //     LL_USART_ClearFlag_IDLE
    // }
    while(1);
}

/**
 * @brief  
 * @param  
 * @retval 
 */
uint16_t uart_buffer_size_get(void)
{
    return DEBUG_UART_RX_BUFFER_SIZE;
}

/**
 * @brief  
 * @param  
 * @retval 
 */
uint16_t uart_curr_pos_get(void)
{
    return (DEBUG_UART_RX_BUFFER_SIZE - LL_DMA_GetDataLength(DEBUG_UART_RX_DMA, DEBUG_UART_RX_DMA_STREAM));
}

/**
 * @brief  
 * @param  
 * @retval 
 */
uint8_t bsp_uart_receive(uint8_t *pdata, uint16_t size, uint32_t timeout)
{
    return HAL_UART_Receive(&_uart_handle, pdata, size, timeout);
}

/**
 * @brief  
 * @param  
 * @retval 
 */
uint8_t bsp_uart_transmit(uint8_t *pdata, uint16_t size, uint32_t timeout)
{
    return HAL_UART_Transmit(&_uart_handle, pdata, size, timeout);
}

/**
 * @brief  
 * @param  
 * @retval 
 */
void bsp_uart_flush_drregister(void)
{
    __HAL_UART_FLUSH_DRREGISTER(&_uart_handle);
}

/**
 * @brief  
 * @param  
 * @retval 
 */
uint32_t bsp_uart_get_state(void)
{
    return _uart_handle.gState;
}

/**
 * @brief  
 * @param  
 * @retval 
 */
void bsp_uart_set_state(uint32_t state)
{
    _uart_handle.gState = state;
}

/**
 * @brief  
 * @param  
 * @retval 
 */
int fputc(int ch, FILE *f)
{
    uint8_t tran = 0;
    tran = (char)(ch & 0x00FF);
    HAL_UART_Transmit(&_uart_handle, &tran, 1, HAL_MAX_DELAY);
    return (ch);
}
